JavaScript is partly an object-oriented language.
To learn JavaScript, we got to learn the object-oriented parts of JavaScript.
In this article, we’ll look at copying objects.
Deep Copy
We can deep copy an object by copying an object’s properties recursively from the source object to the target object.
For instance, we can write:
function deepCopy(source, target = {}) {
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object') {
target[key] = Array.isArray(source[key]) ? [] : {};
deepCopy(source[key], target[key]);
} else {
target[key] = source[key];
}
}
}
return target;
}
We loop through each key of the source
.
Then we check each property if it’s an own property.
Then we check if the source[key]
object is an object.
If source[key]
is an array, then we create an array, then we do the copying.
If it’s an object, then we call deepCopy
recursively to make the copy.
Otherwise, we assign the value from the source
to the target
.
Once that’s all done, we return the target
.
Then we can use it by writing:
const foo = {
a: 1,
b: {
c: 2
}
}
const bar = deepCopy(foo, {});
console.log(bar);
deepCopy
will copy all the own properties from foo
to bar
recursively.
So bar
is:
{
"a": 1,
"b": {
"c": 2
}
}
Array.isArray
lets us check if something is an array regardless of context.
Using object() Method
We can create an object
function to create a function that returns an instance of a constructor.
This suggestion is from Douglas Crockford and it makes setting the prototype easy since it takes the prototype object.
For instance, we can write:
function object(proto) {
function F() {}
F.prototype = proto;
return new F();
}
We create the object
function with the proto
property.
Then we set that as the F
‘s prototype
.
And we return an instance of F
.
This is different from Object.create
since we have an instance of the constructor.
We can then use it by writing:
const obj = object({
foo: 1
});
Then obj
would inherit from the object we passed in.
Mix Prototypal Inheritance and Copying Properties
We can mix prototypical inheritance with copying properties.
To do that, we can expand the object
function by writing:
function object(proto, moreProps) {
function F() {}
F.prototype = proto;
const f = new F();
return {
f,
...moreProps
};
}
const obj = object({
foo: 1
}, {
bar: 2
});
We add a moreProps
parameter to the object
function, which lets us add more properties by passing in the 2nd argument to it.
moreProps
is spread into the object we return so that we return the new object.
Therefore, obj
is {f: F, bar: 2}
since we inherit from F.prototype
and moreProps
.
Conclusion
We can mix prototypical inheritance with copying properties to get all the properties we want in an object.
A deep copy can be done by recursively copying properties from the source object to the target.